using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;

public class PanelManager : MonoBehaviour
{
    private static PanelManager instance;
    public static PanelManager Instance => instance;

    private Dictionary<string, BasePanel> panelCache = new Dictionary<string, BasePanel>();

    [SerializeField] private Transform panelParent;

    private void Awake()
    {
        if (instance == null)
        {
            instance = this;
            DontDestroyOnLoad(gameObject);
        }
        else
        {
            Destroy(gameObject);
        }
    }

    public void OpenPanel<T>(object data = null, Action<T> callback = null) where T : BasePanel
    {
        string panelName = typeof(T).Name;
        if (panelCache.TryGetValue(panelName, out BasePanel panel))
        {
            ShowPanel(panel as T, callback, data);
        }
        else
        {
            StartCoroutine(LoadPanelAsync<T>(callback, data));
        }
    }

    private IEnumerator LoadPanelAsync<T>(Action<T> callback = null, object data = null) where T : BasePanel
    {
        string panelName = typeof(T).Name;
        string path = "PreLoadPrefabs/" + panelName; // 假设所有面板预制件都在 "Prefabs/UI/" 目录下

        ResourceRequest request = Resources.LoadAsync<GameObject>(path);
        yield return request;

        if (request.asset == null)
        {
            Debug.LogError($"Failed to load panel: {panelName}");
            yield break;
        }

        GameObject panelObj = Instantiate(request.asset as GameObject, panelParent);
        T panel = panelObj.GetComponent<T>();

        if (panel == null)
        {
            Debug.LogError($"Panel {panelName} doesn't have {panelName} component");
            yield break;
        }

        panelCache[panelName] = panel;
        ShowPanel(panel, callback, data);
    }

    private void ShowPanel<T>(T panel, Action<T> callback = null, object data = null) where T : BasePanel
    {
        if (panel is IInitializable initializable)
        {
            initializable.Initialize(data);
        }

        panel.gameObject.SetActive(true);
        panel.OnOpen();
        StartCoroutine(PanelTransitionCoroutine(panel, true, () =>
        {
            // 在过渡动画完成后调用回调
            callback?.Invoke(panel);
        }));
    }

    public void ClosePanel<T>() where T : BasePanel
    {
        string panelName = typeof(T).Name;
        if (panelCache.TryGetValue(panelName, out BasePanel panel))
        {
            StartCoroutine(PanelTransitionCoroutine(panel as T, false));
        }
    }

    private IEnumerator PanelTransitionCoroutine(BasePanel panel, bool isOpening, Action onComplete = null)
    {
        if (isOpening)
        {
            yield return panel.PlayOpenAnimation();
        }
        else
        {
            yield return panel.PlayCloseAnimation();
            panel.gameObject.SetActive(false);
            panel.OnClose();
        }

        onComplete?.Invoke();
    }
}

